﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Bomberman
{
	[Serializable]
	public class BombermanJuego : ISerializable
	{
		private const int maxEnemigos = 3;
		public const int dimencionX = 16;
		public const int dimencionY = 10;
		private int porcentajeObstaculos;
		private Mapa mapa;
		private Jugador jugador;
		private List<Enemigo> enemigos = new List<Enemigo>();
		private List<Bomba> bombas = new List<Bomba>();

		public Mapa Mapa
		{
			get { return mapa; }
		}

		public Jugador Jugador
		{
			get { return jugador; }
		}

		public List<Enemigo> Enemigos
		{
			get { return enemigos; }
		}

		public List<Bomba> Bombas
		{
			get { return bombas; }
		}

		public BombermanJuego()
		{ 
		
		}

		public BombermanJuego(SerializationInfo info, StreamingContext ctxt)
		{
			this.porcentajeObstaculos = (int)info.GetValue("porcentajeObstaculos", typeof(int));
			this.mapa = (Mapa)info.GetValue("mapa", typeof(Mapa));
			this.jugador = (Jugador)info.GetValue("jugador", typeof(Jugador));

			Enemigo[] enemigosCargados = (Enemigo[])info.GetValue("enemigos", typeof(Enemigo[]));
			this.enemigos = enemigosCargados.ToList<Enemigo>();

			Bomba[] bombasCargadas = (Bomba[])info.GetValue("bombas", typeof(Bomba[]));
			this.bombas = bombasCargadas.ToList<Bomba>();
		}

		public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
		{
			info.AddValue("porcentajeObstaculos", this.porcentajeObstaculos);
			info.AddValue("mapa", this.mapa);
			info.AddValue("jugador", this.jugador);
			info.AddValue("enemigos", this.enemigos.ToArray());
			info.AddValue("bombas", this.bombas.ToArray());
		}

		public void CargarJuegoPrevio(BombermanJuego bombermanJuegoCargado)
		{
			this.porcentajeObstaculos = bombermanJuegoCargado.porcentajeObstaculos;
			this.mapa = bombermanJuegoCargado.mapa;
			this.jugador = bombermanJuegoCargado.jugador;
			this.enemigos = bombermanJuegoCargado.enemigos;
			this.bombas = bombermanJuegoCargado.bombas;
		}

		public void EmpezarJuego(int porcentajeObstaculos)
		{
			mapa = new Mapa(dimencionX, dimencionY);
			this.porcentajeObstaculos = porcentajeObstaculos;
			mapa.GenerarMapa(this.porcentajeObstaculos);

			jugador = new Jugador(20, 10);
			CrearEnemigos();

			AgregarPersonaje(jugador);

			foreach (Enemigo enemigo in enemigos)
			{
				AgregarPersonaje(enemigo);
			}

		}

		public void TerminarJuegoYRecomenzar()
		{
			enemigos = new List<Enemigo>();
			bombas = new List<Bomba>();
			jugador = null;
			mapa = null;

			EmpezarJuego(this.porcentajeObstaculos);
		}

		private void CrearEnemigos()
		{
			Random r = new Random();
			
			int cant = r.Next(maxEnemigos);
			for (int i = 0; i < cant; i++)
				enemigos.Add(new Bombardero(5, 30, new ControladorTerrestre(), "Cecilio"));
			
			cant = r.Next(maxEnemigos);
			for (int i = 0; i < cant; i++)	
				enemigos.Add(new Tanque(10, 20, "Los López Reggaé"));

			cant = r.Next(maxEnemigos);
			for (int i = 0; i < cant; i++)
				enemigos.Add(new Bombardero(5, 30, new ControladorAlado(), "Los López Reggaé Alados"));
		}

		private void AgregarPersonaje( Personaje personaje )
		{ 
			Random random = new Random();
			Casillero casillero;

			while (true)
			{
				int posX = random.Next(mapa.DimencionX);
				int posY = random.Next(mapa.DimencionY);

				casillero = mapa.VerCasillero(posX, posY);
				if (casillero.ContenidoPosicionable.Contar() == 0) break;
			}

			personaje.Posicionar(casillero);
		}

		public void Update()
		{
			if (mapa.TerminoPartida())
			{
				TerminarJuegoYRecomenzar();
				return;
			}

			jugador.Update();

			foreach (Enemigo enemigo in enemigos)
			{
				enemigo.Update();
				enemigo.Mover();
				enemigo.Atacar();
			}

			for (int fila = 0; fila < mapa.DimencionX; fila++)
			{
				for (int columna = 0; columna < mapa.DimencionY; columna++)
				{
					(mapa.VerCasillero(fila, columna)).Update();
				}
			}
		}

		public void JugadorDejarBomba()
		{
			
			if (jugador.Vida == 0) return;

			Bomba nuevaBomba = jugador.DejarBomba();
			if (nuevaBomba == null) return;
			nuevaBomba.Activar();
		}
		
		public void MoverJugador(String direccion)
		{
			if (direccion == null) return;

			Casillero casillero = jugador.Posicion();
			Casillero nuevoCasillero = casillero.Adyacentes[direccion];

			if (nuevoCasillero == null) return;

			jugador.Mover(nuevoCasillero);
		}


		public bool SigueActivo()
		{
			return (jugador.Vida > 0);
		}
        
        public bool SiguenActivosLosEnemigos()
        {
            bool estaAlgunoVivo = false;
            foreach (Enemigo enemigo in enemigos)
            {
                if (enemigo.Vida > 0) estaAlgunoVivo = true;
            }
            return estaAlgunoVivo;
        }
	}
}
